//
// Created by shaowenhan on 2020/4/27.
//

#include "ReadMDVRPInstance.h"
#if defined(MDVRP) or defined(MDOVRP)

void ReadMDVRPInstance::allocateSpaceForMembers()
{
    int nodeNum = m_instance.depotNum+m_instance.cusNum;
    m_xs.resize(nodeNum);
    m_ys.resize(nodeNum);
#if defined(MDVRP)
    m_instance.serviceTimes.resize(nodeNum);
#endif
    m_instance.distances.resize(nodeNum, vector<double>(nodeNum, 0));
    m_instance.nodeDemands.resize(nodeNum);
}

void ReadMDVRPInstance::readProblemTypeVehicleAndNodeNumber()
{
    auto line = m_readInstanceWrapper.readLine();
    auto integers = m_readInstanceWrapper.integersInLine(line, m_size, m_separators);
    if(integers[0] == 2)
#if defined(MDVRP)
        m_instance.instanceType = "MDVRP";
#elif defined(MDOVRP)
        m_instance.instanceType = "MDOVRP";
#endif
#if defined(MDVRP)
    m_instance.tourNum = integers[1];
#endif
    m_instance.cusNum = integers[2];
    m_instance.depotNum = integers[3];
    m_instance.initialNonCusNum();
    m_instance.initialTotalNodeNum();
}

void ReadMDVRPInstance::readDurationTimeAndLoad()
{
    auto line = m_readInstanceWrapper.readLine();
    auto integers = m_readInstanceWrapper.integersInLine(line, m_size, m_separators);
#if defined(MDVRP)
    m_instance.duration = integers[0];
#endif
    m_instance.vehicleCap = integers[1];
    for(int i = 1; i < m_instance.depotNum; i++)
    {
        line = m_readInstanceWrapper.readLine();
        integers = m_readInstanceWrapper.integersInLine(line, m_size, m_separators);
        if(
#if defined(MDVRP)
                m_instance.duration != integers[0] or
#endif
        m_instance.vehicleCap != integers[1])
        {
            DLOG(ERROR)<<"vehicle are different for different depots"<<endl;
            exit(EXIT_FAILURE);
        }
    }
#if defined(MDVRP)
    if(m_instance.duration == 0)
        m_instance.duration = INT_MAX;
#endif
}

void ReadMDVRPInstance::readNode(int nodeIndex)
{
    auto line = m_readInstanceWrapper.readLine();
    auto doubles = m_readInstanceWrapper.doublesInLine(line, m_size, m_separators);
    m_xs[nodeIndex] = doubles[1];
    m_ys[nodeIndex] = doubles[2];
#if defined(MDVRP)
    m_instance.serviceTimes[nodeIndex] = int(doubles[3]);
#endif
    m_instance.nodeDemands[nodeIndex] = int(doubles[4]);
}

void ReadMDVRPInstance::readNodes()
{
    for(int i = m_instance.depotNum; i < m_instance.depotNum+m_instance.cusNum; i++)
        readNode(i);
    for(int i = 0; i < m_instance.depotNum; i++)
        readNode(i);
}

double ReadMDVRPInstance::powOfNum(double num)
{
    return num*num;
}

void ReadMDVRPInstance::computeDistances()
{
    for(int i = 0; i < m_instance.depotNum+m_instance.cusNum; i++)
    {
        for(int j = 0; j < m_instance.depotNum+m_instance.cusNum; j++)
        {
            m_instance.distances[i][j] = sqrt(double(powOfNum(m_xs[i] - m_xs[j]) + powOfNum(m_ys[i] - m_ys[j])));
        }
    }
#if defined(MDOVRP)
    for(int cus = m_instance.depotNum; cus < m_instance.depotNum+m_instance.cusNum; cus++){
        for(int depot = 0; depot < m_instance.depotNum; depot++)
            m_instance.distances[cus][depot] = 0;
    }
#endif
}

Instance ReadMDVRPInstance::obtainInstance() const
{
    return m_instance;
}

#endif